import java.util.ArrayList;


public class SignalUtil {
	static public void calculateControlDelay(ArrayList<NetworkLink> links, ArrayList<NetworkNode> nodes)
	{
//		int k=0;
//		if(k==0)
//		{
//			return;
//		}
		for(int i=0;i<nodes.size();i++)
		{
			NetworkNode node=nodes.get(i);
			ArrayList<NetworkLink> group1Link=node.comingLinksEW;
			ArrayList<NetworkLink> group2Link=node.comingLinksNS;
			
			double group1MajorVC=0;
			double group2MajorVC=0;
			int group1MajorVolume=0;
			int group2MajorVolume=0;
			int group1MajorSaturation=0;
			int group2MajorSaturation=0;
			for (int j=0;j<group1Link.size();j++)
			{
				NetworkLink link=group1Link.get(j);
				double VC=(double)link.flow/(double)link.capacity;
				if (VC>group1MajorVC)
				{
					group1MajorVC=VC;
					group1MajorVolume=link.flow;
					group1MajorSaturation=link.capacity;
				}
			}
			for (int j=0;j<group2Link.size();j++)
			{
				NetworkLink link=group2Link.get(j);
				double VC=(double)link.flow/(double)link.capacity;
				if (VC>group2MajorVC)
				{
					group2MajorVC=VC;
					group2MajorVolume=link.flow;
					group1MajorSaturation=link.capacity;
				}
			}
			int cycleLength=getCycleLength(4*2, 60, 120, 0.9*(group1MajorSaturation+group2MajorSaturation), group1MajorVolume+group2MajorVolume);
			double green1=getGreenTime(cycleLength, 8, group1MajorVC, group1MajorVC+group2MajorVC);
			double green2=getGreenTime(cycleLength, 8, group2MajorVC, group1MajorVC+group2MajorVC);
			double delay1=getUniformControlDelay(cycleLength, green1, group1MajorVC);
			double delay2=getUniformControlDelay(cycleLength, green2, group2MajorVC);
			for (int j=0;j<group1Link.size();j++)
			{
				NetworkLink link=group1Link.get(j);
				link.setControlDelay((int)delay1);
				link.setTravelTime(link.calculateTravelTime());
			}
			for (int j=0;j<group2Link.size();j++)
			{
				NetworkLink link=group2Link.get(j);
				link.setControlDelay((int)delay2);
				link.setTravelTime(link.calculateTravelTime());
			}
			System.out.println("Signal: Cycle - "+cycleLength+"; Green 1 - "+green1+"; Green 2 - "+green2);
			System.out.println("Delay: Delay1 - "+delay1+"; Delay 2 - "+delay2);
		}
		
	}
	static public int getCycleLength(double totalLostTime,int minimumCycle, int maximumCycle, double referenceSumFlow, int criticalSumVolume)
	{
		int C=(int) (totalLostTime/(1-Math.min(referenceSumFlow, criticalSumVolume)/referenceSumFlow));
		if(C>maximumCycle)
		return maximumCycle;
		if (C<minimumCycle)
			return minimumCycle;
		return C;
	}
	static public double getGreenTime(int cycleLength, double lostTime, double VC, double sumVC)
	{
		double g=(cycleLength-lostTime)*(VC/sumVC);
		return g;
	}
	
	static public double getUniformControlDelay(int cycleLength, double greenTime, double VC)
	{
		double d=0.5*cycleLength*Math.pow((1-greenTime/cycleLength), 2)/(1-Math.min(1, VC)*greenTime/cycleLength);
		return d;
	}
}
